﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Globalization;

namespace UpYunLibrary
{
    class Program
    {
        static void Main(string[] args)
        {
            UpYun uy = new UpYun("空间名称", "操作员用户名", "操作员密码");
            Hashtable headers = new Hashtable();
            //uy.delete("tes\ttd.jpg", headers);
            /*FileStream fs = new FileStream("c:\\ff.JPG", FileMode.Open, FileAccess.Read);
            BinaryReader r = new BinaryReader(fs);
            byte[] postArray = r.ReadBytes((int)fs.Length);
            bool b = uy.writeFile("testtest.jpg",postArray,headers);
            Console.WriteLine(b);*/
            bool b = uy.deleteFile("testtest.jpg",headers);
            Console.WriteLine(b);
            //string str = "date="+postArray.ToString();
            //string str = "date=" + Encoding.ASCII.GetString(postArray, 0, postArray.Length);
            //ArrayList str = uy.readDir("");
            //foreach (FolderItem var in str)
            //{
            //    Console.WriteLine(var.filename);
            //}
            ArrayList str = uy.readDir("");
            foreach (var item in str)
            {
                FolderItem a = (FolderItem)item;
                Console.WriteLine(a.filename);
            }
            
            //bool str = uy.delete("test1", headers);
            Console.WriteLine(headers["Authorization"]);
            //Console.WriteLine(str);

            Console.Read();
        }
    }

    //目录条目类
    public class FolderItem
    {
        public string filename;
        public string filetype;
        public int size;
        public int number;
        public FolderItem(string filename, string filetype, int size, int number)
        {
            this.filename = filename;
            this.filetype = filetype;
            this.size = size;
            this.number = number;
        }
    }

    public class UpYun
    {
        private string bucketname;
        private string username;
        private string password;
        private bool upAuth = false;
        private string api_domain = "v0.api.upyun.com";
        private string DL = "/";


        /**
	    * 初始化 UpYun 存储接口
	    * @param $bucketname 空间名称
	    * @param $username 操作员名称
	    * @param $password 密码
	    * return UpYun object
	    */
        public UpYun(string bucketname, string username, string password)
        {
            this.bucketname = bucketname;
            this.username = username;
            this.password = password;
        }

        /**
	    * 切换 API 接口的域名
	    * @param $domain {默认 v0.api.upyun.com 自动识别, v1.api.upyun.com 电信, v2.api.upyun.com 联通, v3.api.upyun.com 移动}
	    * return null;
	    */
        public void setApiDomain(string domain)
        {
            this.api_domain = domain;
        }

        /**
	    * 是否启用 又拍签名认证
	    * @param upAuth {默认 false 不启用(直接使用basic auth)，true 启用又拍签名认证}
		* 开启又拍签名认证需要 .net 4.0以上
	    * return null;
	    */
        public void setAuthType(bool upAuth)
        {
            this.upAuth = upAuth;
        }

        private void upyunAuth(Hashtable headers, string method, string uri, HttpWebRequest request)
        {
            DateTime dt = DateTime.UtcNow;
            string date = dt.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'", CultureInfo.CreateSpecificCulture("en-US"));
            //request.Date = dt;
            //headers.Add("Date", date);
            string auth;
            if (request.ContentLength != -1)
                auth = md5(method + '&' + uri + '&' + date + '&' + request.ContentLength + '&' + md5(this.password));
            else
                auth = md5(method + '&' + uri + '&' + date + '&' + 0 + '&' + md5(this.password));
            headers.Add("Authorization", "UpYun " + this.username + ':' + auth);
        }

        private string md5(string str)
        {
            MD5 m = new MD5CryptoServiceProvider();
            byte[] s = m.ComputeHash(UnicodeEncoding.UTF8.GetBytes(str));
            string resule = BitConverter.ToString(s);
            resule = resule.Replace("-", "");
            return resule.ToLower();
        }
        private bool delete(string path, Hashtable headers)
        {
            HttpWebResponse resp;
            byte[] a = null;
            resp = newWorker("DELETE", DL + this.bucketname + DL + path, a, headers);
            if ((int)resp.StatusCode == 200)
                return true;
            else
                return false;
        }
        private HttpWebResponse newWorker(string method, string Url, byte[] postData, Hashtable headers)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://" + api_domain + Url);

            
            request.Method = method;

            if (postData != null)
            {
                request.ContentLength = postData.Length;
                request.KeepAlive = true;
            }

            if (this.upAuth)
            {
                upyunAuth(headers, method, Url, request);
            }
            else
            {
                request.Headers.Add("Authorization", "Basic " +
                    Convert.ToBase64String(new System.Text.ASCIIEncoding().GetBytes(this.username + ":" + this.password)));
            }
            foreach (DictionaryEntry var in headers)
            {
                request.Headers.Add(var.Key.ToString(), var.Value.ToString());
            }

            if (postData != null)
            {
                Stream dataStream = request.GetRequestStream();
                dataStream.Write(postData, 0, postData.Length);
                dataStream.Close();
            }
            HttpWebResponse response;
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (Exception e)
            {
                throw e;
            }

            return response;
        }

        /**
	    * 获取总体空间的占用信息
	    * return 空间占用量，失败返回 null
	    */

        public int getBucketUsage(string Url, Hashtable headers)
        {
            int size;
            byte[] a = null;
            HttpWebResponse resp = newWorker("GET",DL + this.bucketname + DL + Url + "?usage", a, headers);
            try
            {
                StreamReader sr = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);
                string strhtml = sr.ReadToEnd();
                size = int.Parse(strhtml);
            }
            catch (Exception)
            {
                size = 0;
            }
            return size;
        }

        /**
           * 获取某个子目录的占用信息
           * @param $path 目标路径
           * return 空间占用量，失败返回 null
           */
        public int getFolderUsage(string Url)
        {
            Hashtable headers = new Hashtable(); ;

            return getBucketUsage(Url, headers);
        }
        /**
	    * 创建目录
	    * @param $path 目录路径
	    * return true or false
	    */
        public bool mkDir(string path, Hashtable headers)
        {
            headers.Add("folder", "create");
            HttpWebResponse resp;
            byte[] a = new byte[0];
            resp = newWorker("POST", DL + this.bucketname + DL + path, a, headers);
            if ((int)resp.StatusCode == 200)
                return true;
            else
                return false;
        }

        /**
	    * 删除目录
	    * @param $path 目录路径
	    * return true or false
	    */
        public bool rmDir(string path, Hashtable headers)
        {
            return delete(path, headers);
        }

        /**
	    * 读取目录列表
	    * @param $path 目录路径
	    * return array 数组 或 null
	    */
        public ArrayList readDir(string url)
        {
            Hashtable headers = new Hashtable();
            byte[] a = null;
            HttpWebResponse resp = newWorker("GET",DL + this.bucketname + DL + url, a, headers);
            StreamReader sr = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);
            string strhtml = sr.ReadToEnd();
            strhtml = strhtml.Replace("\t", "\\");
            strhtml = strhtml.Replace("\n", "\\");
            string[] ss = strhtml.Split('\\');
            int i = 0;
            ArrayList AL = new ArrayList();
            while (i < ss.Length)
            {
                FolderItem fi = new FolderItem(ss[i], ss[i + 1], int.Parse(ss[i + 2]), int.Parse(ss[i + 3]));
                AL.Add(fi);
                i += 4;
            }
            return AL;
        }


        /**
	    * 上传文件
	    * @param $file 文件路径（包含文件名）
	    * @param $datas 文件内容 或 文件IO数据流
	    * return true or false
	    */
        public bool writeFile(string path, byte[] data, Hashtable headers)
        {
            HttpWebResponse resp;
            resp = newWorker("POST", DL + this.bucketname + DL + path, data, headers);
            if ((int)resp.StatusCode == 200)
                return true;
            else
                return false;
        }
        /**
	    * 删除文件
	    * @param $file 文件路径（包含文件名）
	    * return true or false
	    */
        public bool deleteFile(string path, Hashtable headers)
        {
            return delete(path, headers);
        }

        /**
	    * 读取文件
	    * @param $file 文件路径（包含文件名）
	    * @param $output_file 可传递文件IO数据流（默认为 null，结果返回文件内容，如设置文件数据流，将返回 true or false）
	    * return 文件内容 或 null
	    */
        public string readFile(string path)
        {
            Hashtable headers = new Hashtable();
            byte[] a = null;
            
            HttpWebResponse resp = newWorker("GET",DL + this.bucketname + DL + path, a, headers);
            StreamReader sr = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);
            string strhtml = sr.ReadToEnd();
            return strhtml;
        }
    }
}
